package com.tbynet.jwp.framework.bean;

/**
 * 分页参数类
 *
 * 核心职责：
 * 1. 封装分页查询的基本参数
 * 2. 提供分页参数验证和默认值设置
 * 3. 计算数据库查询的偏移量
 * 4. 支持多种分页场景
 *
 * 设计原则：
 * - 不可变对象，确保线程安全
 * - 提供便捷的构造方法
 * - 支持参数验证和边界检查
 * - 清晰的API设计
 *
 * @author 佰亿互联
 * @version 1.0
 * @since 2025-11-04
 */
public class PageParams {

    // ========== 配置常量 ==========

    /** 默认分页大小 */
    public static final int DEFAULT_PAGE_SIZE = 20;

    /** 最小分页大小 */
    public static final int MIN_PAGE_SIZE = 1;

    /** 最大分页大小 */
    public static final int MAX_PAGE_SIZE = 100;

    /** 默认页码 */
    public static final int DEFAULT_PAGE_NUMBER = 1;

    // ========== 成员变量 ==========

    /** 当前页码 */
    private final int pageNumber;

    /** 每页大小 */
    private final int pageSize;

    // ========== 构造方法 ==========

    /**
     * 私有构造方法
     *
     * @param pageNumber 页码
     * @param pageSize 每页大小
     */
    private PageParams(int pageNumber, int pageSize) {
        this.pageNumber = pageNumber;
        this.pageSize = pageSize;
    }

    // ========== 静态工厂方法 ==========

    /**
     * 创建分页参数对象
     *
     * @param pageNumber 页码
     * @param pageSize 每页大小
     * @return 分页参数对象
     */
    public static PageParams of(Integer pageNumber, Integer pageSize) {
        int validPageNumber = validatePageNumber(pageNumber);
        int validPageSize = validatePageSize(pageSize);
        return new PageParams(validPageNumber, validPageSize);
    }

    /**
     * 创建分页参数对象（使用默认值）
     *
     * @return 分页参数对象
     */
    public static PageParams defaults() {
        return new PageParams(DEFAULT_PAGE_NUMBER, DEFAULT_PAGE_SIZE);
    }

    /**
     * 创建分页参数对象（指定页码，使用默认分页大小）
     *
     * @param pageNumber 页码
     * @return 分页参数对象
     */
    public static PageParams of(int pageNumber) {
        int validPageNumber = validatePageNumber(pageNumber);
        return new PageParams(validPageNumber, DEFAULT_PAGE_SIZE);
    }

    // ========== 验证方法 ==========

    /**
     * 验证页码
     *
     * @param pageNumber 页码
     * @return 验证后的页码
     */
    private static int validatePageNumber(Integer pageNumber) {
        if (pageNumber == null || pageNumber < DEFAULT_PAGE_NUMBER) {
            return DEFAULT_PAGE_NUMBER;
        }
        return pageNumber;
    }

    /**
     * 验证分页大小
     *
     * @param pageSize 分页大小
     * @return 验证后的分页大小
     */
    private static int validatePageSize(Integer pageSize) {
        if (pageSize == null || pageSize < MIN_PAGE_SIZE) {
            return DEFAULT_PAGE_SIZE;
        }
        return Math.min(pageSize, MAX_PAGE_SIZE);
    }

    // ========== 计算方法 ==========

    /**
     * 计算数据库查询的偏移量
     *
     * @return 偏移量
     */
    public int getOffset() {
        return (pageNumber - 1) * pageSize;
    }

    /**
     * 计算总页数
     *
     * @param totalCount 总记录数
     * @return 总页数
     */
    public int getTotalPages(long totalCount) {
        if (totalCount <= 0) {
            return 0;
        }
        return (int) Math.ceil((double) totalCount / pageSize);
    }

    /**
     * 检查是否有上一页
     *
     * @return 是否有上一页
     */
    public boolean hasPrevious() {
        return pageNumber > DEFAULT_PAGE_NUMBER;
    }

    /**
     * 检查是否有下一页
     *
     * @param totalCount 总记录数
     * @return 是否有下一页
     */
    public boolean hasNext(long totalCount) {
        return pageNumber < getTotalPages(totalCount);
    }

    /**
     * 获取上一页页码
     *
     * @return 上一页页码，如果没有上一页返回当前页码
     */
    public int getPreviousPage() {
        return hasPrevious() ? pageNumber - 1 : pageNumber;
    }

    /**
     * 获取下一页页码
     *
     * @param totalCount 总记录数
     * @return 下一页页码，如果没有下一页返回当前页码
     */
    public int getNextPage(long totalCount) {
        return hasNext(totalCount) ? pageNumber + 1 : pageNumber;
    }

    // ========== Getter方法 ==========

    public int getPageNumber() {
        return pageNumber;
    }

    public int getPageSize() {
        return pageSize;
    }

    // ========== 链式方法 ==========

    /**
     * 创建新的分页参数对象（修改页码）
     *
     * @param newPageNumber 新页码
     * @return 新的分页参数对象
     */
    public PageParams withPageNumber(int newPageNumber) {
        int validPageNumber = validatePageNumber(newPageNumber);
        return new PageParams(validPageNumber, this.pageSize);
    }

    /**
     * 创建新的分页参数对象（修改分页大小）
     *
     * @param newPageSize 新分页大小
     * @return 新的分页参数对象
     */
    public PageParams withPageSize(int newPageSize) {
        int validPageSize = validatePageSize(newPageSize);
        return new PageParams(this.pageNumber, validPageSize);
    }

    // ========== 工具方法 ==========

    /**
     * 转换为Map
     *
     * @return 包含分页参数的Map
     */
    public java.util.Map<String, Object> toMap() {
        java.util.Map<String, Object> map = new java.util.HashMap<>();
        map.put("pageNumber", pageNumber);
        map.put("pageSize", pageSize);
        map.put("offset", getOffset());
        return map;
    }

    /**
     * 转换为字符串表示
     *
     * @return 分页参数的字符串表示
     */
    @Override
    public String toString() {
        return "PageParams{" +
                "pageNumber=" + pageNumber +
                ", pageSize=" + pageSize +
                ", offset=" + getOffset() +
                '}';
    }

    /**
     * 比较两个分页参数对象是否相等
     *
     * @param o 比较对象
     * @return 是否相等
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PageParams that = (PageParams) o;
        return pageNumber == that.pageNumber && pageSize == that.pageSize;
    }

    /**
     * 计算哈希值
     *
     * @return 哈希值
     */
    @Override
    public int hashCode() {
        return java.util.Objects.hash(pageNumber, pageSize);
    }
}